package com.tanhua.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.exception.BusinessException;
import com.tanhua.interceptor.UserHolder;
import model.domain.UserInfo;
import model.mongo.Visitors;
import model.vo.ErrorResult;
import model.vo.MovementsVo;
import model.vo.PageResult;
import model.vo.VisitorsVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.dubbo.api.MovementApi;
import model.mongo.Movement;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    /**
     * 发布动态
     */
    public void publishMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        if (StringUtils.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }

        Long userId = UserHolder.getUserId();

        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(upload);
        }

        movement.setUserId(userId);
        movement.setMedias(medias);
        movementApi.publish(movement);
    }

    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        PageResult pageResult = movementApi.findByUserId(userId, page, pagesize);

        List<Movement> items = (List<Movement>) pageResult.getItems();
        if (items == null) {
            return pageResult;
        }

        UserInfo userInfo = userInfoApi.findById(userId);
        ArrayList<MovementsVo> movementsVos = new ArrayList<>();
        for (Movement item : items) {
            movementsVos.add(MovementsVo.init(userInfo, item));
        }
        pageResult.setItems(movementsVos);
        return pageResult;
    }

    //查询好友动态
    public PageResult findFriendMovements(Integer page, Integer pagesize) {
        Long userId = UserHolder.getUserId();

        List<Movement> movements = movementApi.findFriendMovements(page, pagesize, userId);

        return getPageResult(page, pagesize, movements);
    }

    /**
     * 查询推荐动态
     */
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        String redisValue = redisTemplate.opsForValue().get(
                Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId());
        List<Movement> movements = Collections.EMPTY_LIST;
        if (StringUtils.isEmpty(redisValue)) {
            movements = movementApi.randomMovements(pagesize);
        } else {
            String[] values = redisValue.split(",");
            if ((page - 1) * pagesize < values.length) {
                List<Long> pids = Arrays.stream(values).skip((page - 1) * pagesize).limit(pagesize)
                        .map(v -> Long.valueOf(v))
                        .collect(Collectors.toList());
                movements = movementApi.findMovementsByPids(pids);
            }
        }
        return getPageResult(page, pagesize, movements);
    }

    private PageResult getPageResult(Integer page, Integer pagesize, List<Movement> movements) {
        if (CollUtil.isEmpty(movements)) {
            return new PageResult();
        }

        List<Long> userIds = CollUtil.getFieldValues(movements, "userId", Long.class);

        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);

        ArrayList<MovementsVo> movementsVos = new ArrayList<>();
        for (Movement movement : movements) {
            UserInfo userInfo = map.get(movement.getUserId());

            if (userInfo != null) {
                MovementsVo movementsVo = MovementsVo.init(userInfo, movement);

                String likeKey = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String likeHashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(likeKey, likeHashKey)) {
                    movementsVo.setHasLiked(1);
                }

                String loveKey = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String loveHashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(loveKey, loveHashKey)) {
                    movementsVo.setHasLoved(1);
                }

                movementsVos.add(movementsVo);
            }
        }
        return new PageResult(page, pagesize, 0L, movementsVos);
    }

    public MovementsVo findById(String movementId) {
        Movement movement = movementApi.findById(movementId);
        if (movement != null) {
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            return MovementsVo.init(userInfo, movement);
        } else {
            return null;
        }
    }

    public List<VisitorsVo> queryVisitorsList() {
        String key = Constants.VISITORS_USER;
        String hashKey = String.valueOf(UserHolder.getUserId());
        String value = (String)redisTemplate.opsForHash().get(key, hashKey);
        Long date = StringUtils.isEmpty(value) ? null:Long.valueOf(value);

        List<Visitors> list = visitorsApi.queryMyVisitors(date, UserHolder.getUserId());

        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<Long> userIds = CollUtil.getFieldValues(list, "visitorUserId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);

        List<VisitorsVo> visitorsVos = new ArrayList<>();
        for (Visitors visitors : list) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            if (userInfo != null) {
                VisitorsVo visitorsVo = VisitorsVo.init(userInfo, visitors);
                visitorsVos.add(visitorsVo);
            }
        }
        return visitorsVos;
    }

}